package master.support;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

/**
 * DAO support class uses SimpleJdbcTemplate
 *
 * Normally, don't need to write a child class
 *
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 */
public class DAOSupport extends SimpleJdbcDaoSupport {

    @Autowired
    @Qualifier("atomikosDataSource")
    private DataSource dataSource;

    @PostConstruct
    private void init() {
        setDataSource(dataSource);
        // 会默认创建
//        getJdbcTemplate().setExceptionTranslator(new SQLErrorCodeSQLExceptionTranslator(dataSource);
    }

    public NamedParameterJdbcOperations getNamedParameterJdbcTemplate() {
        return getSimpleJdbcTemplate().getNamedParameterJdbcOperations();
    }

    public int insertDomainObject(DomainObject domainObject){
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildInsertSQL(domainObject.getClass()), new BeanPropertySqlParameterSource(domainObject));
    }

    public int deleteDomainObject(DomainObject domainObject){
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildDeleteSQLById(domainObject.getClass()), new BeanPropertySqlParameterSource(domainObject));
    }

    public int deleteDomainObjectById(Class domainClass, long id){
        Map<String, Object> paramMap = new Hashtable<String, Object>(1);
        paramMap.put("id", id);
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildDeleteSQLById(domainClass),paramMap);
    }

    public int deleteDomainObjectByIdIn(Class domainClass, long... ids){
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildDeleteSQLByIdIn(domainClass, ids), new HashMap<String, Object>(1));
    }

    public int deleteDomainObjectByWhere(Class domainClass, String whereSql, Map<String, Object> paramMap){
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildDeleteSQLById(domainClass),paramMap);
    }

    public int updateDomainObject(DomainObject domainObject){
        return getNamedParameterJdbcTemplate().update(SQLGenerator.buildUpdateSQL(domainObject.getClass()), new BeanPropertySqlParameterSource(domainObject));
    }

    public <T extends DomainObject> T getDomainObject(Class<T> domainClass, long id) {
        Map<String, Object> paramMap = new HashMap<String, Object>(1);
        paramMap.put("id", id);
        return getNamedParameterJdbcTemplate().queryForObject(SQLGenerator.buildSelectSQLById(domainClass),  paramMap, new BeanPropertyRowMapper<T>(domainClass));
    }

    public <T extends DomainObject> List<T> selectAllDomainObjects(Class<T> domainClass) {
        return getNamedParameterJdbcTemplate().query(SQLGenerator.buildSelectSQL(domainClass), new HashMap<String, Object>(1), new BeanPropertyRowMapper<T>(domainClass));
    }

    public <T extends DomainObject> List<T> selectDomainObjectsByWhere(Class<T> domainClass, String whereSql, Map<String, Object> paramMap) {
        return getNamedParameterJdbcTemplate().query(SQLGenerator.buildSelectSQLByWhere(domainClass, whereSql), paramMap, new BeanPropertyRowMapper<T>(domainClass));
    }

    public <T extends DomainObject> List<T> selectDomainObjectsByIdIn(Class<T> domainClass, long... ids) {
        return getNamedParameterJdbcTemplate().query(SQLGenerator.buildSelectSQLByIdIn(domainClass, ids), new HashMap<String, Object>(1), new BeanPropertyRowMapper<T>(domainClass));
    }

    public <T extends DomainObject> List<T> selectDomainObjectsByColumnIn(Class<T> domainClass, String column, Object... values) {
        return getNamedParameterJdbcTemplate().query(SQLGenerator.buildSelectSQLByColumnIn(domainClass, column, values), new HashMap<String, Object>(1), new BeanPropertyRowMapper<T>(domainClass));
    }

}
